package service

import (
	"context"
	"fmt"
	"mygf2/internal/model/entity"
	"mygf2/internal/service/internal/dao"
	"mygf2/internal/service/internal/do"
	"os"
	"strings"

	"github.com/gogf/gf/v2/crypto/gmd5"
	"github.com/gogf/gf/v2/database/gdb"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/os/gfile"
	"github.com/gogf/gf/v2/os/gtime"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/gogf/gf/v2/util/guid"
)

type (
	sGatherUrls struct{}
)

var (
	insGatherUrls = sGatherUrls{}
)

func GatherUrls() *sGatherUrls {
	return &insGatherUrls
}
func (s *sGatherUrls) GetPrivateUrl(ctx context.Context, url string) string {
	url = "/" + url
	muster_key := g.Cfg().MustGet(ctx, "aliyunoss.muster_key").String()
	cdnurl := g.Cfg().MustGet(ctx, "aliyunoss.cdnurl").String()
	video_url_expiry := g.Cfg().MustGet(ctx, "aliyunoss.video_url_expiry").Int()
	now := int(gtime.Timestamp())
	expierTime := now - 1800 + video_url_expiry
	sstring := url + "-" + gconv.String(expierTime) + "-0-0-" + muster_key
	fmt.Println(sstring)
	smd5, err := gmd5.EncryptString(sstring)
	if err != nil {
		return ""
	}
	auth_key := "auth_key=" + gconv.String(expierTime) + "-0-0-" + smd5

	url = cdnurl + url + "?" + auth_key
	return url
}
func (s *sGatherUrls) GetInfo(ctx context.Context, id int) (gatherUrls *entity.GatherUrls) {
	//查找数据
	//var gatherUrls *entity.GatherUrls
	err := dao.GatherUrls.Ctx(ctx).Where(do.GatherUrls{
		Id: id,
	}).Scan(&gatherUrls)
	if err != nil {
		return
	}
	//无此条数据
	if gatherUrls == nil {
		return
	}
	if gatherUrls.DownloadUrl != "" {
		//获取授权访问链接
		gatherUrls.DownloadUrl = s.GetPrivateUrl(ctx, gatherUrls.DownloadUrl)
	}
	if gatherUrls.DownCover != "" {
		//获取授权访问链接
		gatherUrls.DownCover = s.GetPrivateUrl(ctx, gatherUrls.DownCover)
	}
	return
}

//入库
func (s *sGatherUrls) GatherInStorage(ctx context.Context, id int, taskChan chan bool) {
	suc := false //是否下载成功
	defer func() {
		taskChan <- suc
	}()
	//查找数据
	var gatherUrls *entity.GatherUrls
	err := dao.GatherUrls.Ctx(ctx).Where(do.GatherUrls{
		Id: id,
	}).Scan(&gatherUrls)
	if err != nil {
		return
	}
	//无此条数据
	if gatherUrls == nil {
		return
	}
	//还没下载
	if gatherUrls.IsDownload != 1 {
		return
	}
	//已入库了
	if gatherUrls.InStorage == 1 {
		return
	}

	//保存到视频库
	//横屏竖屏
	videoScreen := 0
	if gatherUrls.Width > 0 && gatherUrls.Width >= gatherUrls.Height {
		videoScreen = 1
	} else if gatherUrls.Width > 0 && gatherUrls.Width < gatherUrls.Height {
		videoScreen = 2
	}
	videoId := s.GetVideoId(ctx)
	data := g.Map{
		"id":            videoId,
		"review_status": 0,
		"is_show":       0,
		"appid":         "wxe307a054f09a0fcf",
		"video_title":   gatherUrls.Title,
		"video_height":  gatherUrls.Height,
		"video_width":   gatherUrls.Width,
		"video_time":    gatherUrls.Duration,
		"video_url":     gatherUrls.DownloadUrl,
		"thumbnail":     gatherUrls.DownCover,
		"video_tags":    gatherUrls.Tags,
		"video_screen":  videoScreen,
		"backstage":     1,
		"cid":           19,
		"create_user":   187869,
		"create_time":   gtime.Timestamp(),
	}
	_, err = g.DB("video").Model("video").Data(data).Insert()
	if err != nil {
		return
	}
	//修改状态
	//gatherUrls.IsDownload = 1
	//gatherUrls.DownloadUrl = ossUrl
	dao.GatherUrls.Ctx(ctx).Data(g.Map{"in_storage": 1}).Where(do.GatherUrls{
		Id: id,
	}).Update()
	suc = true
	return
}
func (s *sGatherUrls) GetVideoId(ctx context.Context) int64 {
	var videoId int64
	cv, _ := g.Redis().Do(ctx, "INCR", "video:id")
	videoId = cv.Int64()
	if videoId == 1 {
		dvFloat, _ := g.DB("video").Model("video").Max("id")
		dvInt64 := gconv.Int64(dvFloat)
		if dvInt64 > videoId {
			videoId = dvInt64 + 1
			g.Redis().Do(ctx, "SET", "video:id", videoId)
		}
	}
	return videoId
}
func (s *sGatherUrls) GatherDownload(ctx context.Context, id int, taskChan chan bool) {
	suc := false //是否下载成功
	defer func() {
		taskChan <- suc
	}()
	//查找数据
	var gatherUrls *entity.GatherUrls
	err := dao.GatherUrls.Ctx(ctx).Where(do.GatherUrls{
		Id: id,
	}).Scan(&gatherUrls)
	if err != nil {
		return
	}
	//无此条数据
	if gatherUrls == nil {
		return
	}
	//已下载
	if gatherUrls.IsDownload == 1 {
		return
	}
	//没有要下载的资源
	if gatherUrls.NowatermarkUrl == "" {
		return
	}
	//开始下载
	headerMap := g.MapStrStr{}
	if gatherUrls.Source == "抖音" {
		headerMap = DouyinDownloadHeaders
	} else {
		headerMap = KuaishouDownloadHeaders
	}
	headerMap["referer"] = gatherUrls.Url
	r, err := g.Client().SetHeaderMap(headerMap).Get(ctx, gatherUrls.NowatermarkUrl)
	if err != nil {
		return
	}
	pathInfo := g.Cfg().MustGet(ctx, "tempPath")
	file_name := guid.S() + ".mp4"
	localfile := pathInfo.String() + file_name
	err = gfile.PutBytes(localfile, r.ReadAll())
	if err != nil {
		g.Log().Debug(ctx, id, "远程下载出错")
		return
	}
	//上传到oss
	yunfiletmp := "video/gather/" + gtime.Now().Format("Ym") + "/" + file_name
	//'video/video/'.$date.'/'.$file['FatherName'].'/'.$file['ChildrenName'].'/'.$now.'_'.$name.'_short.'.$type;
	ossUrl, err := AliyunOSS.UploadFile(ctx, localfile, yunfiletmp)
	if err != nil {
		g.Log().Debug(ctx, id, err.Error())
		return
	}
	defer func() {
		//删除本地文件
		err = os.Remove(localfile)
		if err != nil {
			g.Log().Debug(ctx, id, "删除文件出错")
		}
	}()
	coverYunPath := ""
	//上传封面图
	if gatherUrls.Cover != "" {
		r, err := g.Client().SetHeaderMap(headerMap).Get(ctx, gatherUrls.Cover)
		if err != nil {
			return
		}
		coverPath := g.Cfg().MustGet(ctx, "tempPath")

		//fileExt := path.Ext(gatherUrls.Cover)
		//exts := strings.Split(fileExt, "?")
		ext := strings.ToLower(gfile.Ext(gatherUrls.Cover))
		needExtMap := map[string]string{".jpg": "jpg", ".png": "png", ".jpeg": "jpeg", ".gif": "gif"}
		if _, ok := needExtMap[ext]; !ok {
			ext = ".jpg"
		}
		coverFileName := guid.S() + ext
		coverLocalFile := coverPath.String() + coverFileName
		err = gfile.PutBytes(coverLocalFile, r.ReadAll())
		if err != nil {
			g.Log().Debug(ctx, id, "远程下载封面图出错", err)
		} else {
			//上传到oss
			coverFiletmp := "video/gather/" + gtime.Now().Format("Ym") + "/" + coverFileName
			//'video/video/'.$date.'/'.$file['FatherName'].'/'.$file['ChildrenName'].'/'.$now.'_'.$name.'_short.'.$type;
			coverYunPath, err = AliyunOSS.UploadFile(ctx, coverLocalFile, coverFiletmp)
			if err != nil {
				g.Log().Debug(ctx, id, err)
			}
		}

		defer func() {
			//删除本地文件
			err = os.Remove(coverLocalFile)
			if err != nil {
				g.Log().Debug(ctx, id, "删除封面图文件出错", err)
			}
		}()
	}

	//修改状态
	//gatherUrls.IsDownload = 1
	//gatherUrls.DownloadUrl = ossUrl
	dao.GatherUrls.Ctx(ctx).Data(g.Map{"is_download": 1, "download_url": ossUrl, "down_cover": coverYunPath}).Where(do.GatherUrls{
		Id: id,
	}).Update()
	suc = true
	return
}
func (s *sGatherUrls) GetList(ctx context.Context, where g.Map, page int, pagesize int) (list gdb.Result) {
	list, err := dao.GatherUrls.Ctx(ctx).Where(where).Offset((page - 1) * pagesize).Limit(pagesize).OrderDesc("id").All()
	if err != nil {
		list = nil
	}
	return
}
func (s *sGatherUrls) GetListCount(ctx context.Context, where g.Map) (count int) {
	count, err := dao.GatherUrls.Ctx(ctx).Where(where).Count()
	if err != nil {
		count = 0
	}
	return
}

// 采集结果入库
func (s *sGatherUrls) GatherInTable(ctx context.Context, aur *entity.GatherUrls) (res *entity.GatherUrls) {
	if aur.NowatermarkUrl == "" {
		return nil
	}
	//去md5
	url_md5, err := gmd5.EncryptString(aur.Url)
	if err != nil {
		return nil
	}
	var gatherUrls *entity.GatherUrls
	err = dao.GatherUrls.Ctx(ctx).Where(do.GatherUrls{
		Source:   aur.Source,
		OriginId: aur.OriginId,
	}).Scan(&gatherUrls)
	if err != nil {
		return nil
	}
	if gatherUrls != nil {
		//已存在
		return gatherUrls
	}
	//插入
	aur.UrlMd5 = url_md5
	id, err := dao.GatherUrls.Ctx(ctx).Data(aur).InsertAndGetId()
	if err != nil || id <= 0 {
		return nil
	}
	err = dao.GatherUrls.Ctx(ctx).Where(do.GatherUrls{
		Id: id,
	}).Scan(&gatherUrls)
	if err != nil {
		return nil
	}
	if gatherUrls != nil {
		//已存在
		return gatherUrls
	}
	return
}
